package Concurrency2.Chapter03_CAS_Atomic.P01_CASUsage;

import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 实现自增的方式
 */
public class T01_AutoIncrement {

    private static final int TURN = 1000000;
    private static final int THREAD_COUNT = 10;
    private static long result = 0L;
    private static CountDownLatch countDownLatch = new CountDownLatch(10);

    public static void autoIncrementWithLock() {
        Object lock = new Object();
        //创建线程任务
        Runnable task = () -> {
            for (int i = 0; i < TURN; i++) {
                synchronized (lock) {
                    result++;
                }
            }
            countDownLatch.countDown();
        };

        //提交线程任务给线程池
        ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_COUNT);
        for (int i = 0; i < THREAD_COUNT; i++) {
            threadPool.submit(task);
        }
        try {
            countDownLatch.await();
            threadPool.shutdownNow();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("Result: " + result);
    }

    public static void autoIncrementWithCas() {
        //获取Unsafe
        //Unsafe unsafe = Unsafe.getUnsafe();
        Unsafe unsafe = null;
        try {
            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafe.setAccessible(true);
            unsafe = (Unsafe) theUnsafe.get(null);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        long resultOffset;
        try {
            resultOffset = unsafe.staticFieldOffset(T01_AutoIncrement.class.getDeclaredField("result"));
            System.out.println("resultOffset:" + resultOffset);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        }


        //修改内存中实例的属性
        Unsafe finalUnsafe = unsafe;
        Runnable task = () -> {
            System.err.println("计算前: result: " + result);
            for (int i = 0; i < TURN; i++) {
                long oldResult = result;
                do {
                    oldResult = result;
                } while (!finalUnsafe.compareAndSwapLong(T01_AutoIncrement.class, resultOffset, oldResult, oldResult + 1));
            }
            countDownLatch.countDown();
            System.out.println("计算完成: result: " + result);
        };
        ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_COUNT);
        for (int i = 0; i < THREAD_COUNT; i++) {
            threadPool.submit(task);
        }
        try {
            countDownLatch.await();
            threadPool.shutdownNow();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("Result: " + result);
    }

    public static void main(String[] args) {
        //autoIncrementWithLock();
        autoIncrementWithCas();
    }
}
